/******************************************************************************
                         COPYRIGHT 1955-2008 by BUPT ISC.
                        北京邮电大学信息安全中心 版权所有
                           Web: http://www.bupt.edu.cn
 *******************************************************************************/
/*******************************************************************************
  文件名： string_utils.c
  项目：   
  模块：   common
  作者：   huangwei
  版本：   0.1
  创建于:  2009-03-17
  描述：
    字符串操作工具类函数

  修改历史：
  日期： 修改人： 修改描述：
  
 *********************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>

#include "string_utils.h"
/*******************字符串函数使用注意****************************
1.除了统计字符串函数外，所有字符串函数不能直接处理常量字符串，即只能处理字符串数组


*********************************************************/

/******************************************************************************
  函数名：ltrim
  功能描述：
    去除字符串首部的空白（空格、tab、回车、换行）

  输入参数：
    char * 待处理字符串

  输出参数：
    char * 处理后的字符串

  返回值：
    char * 处理后的字符串
 *****************************************************************************/
char *ltrim(char *pcSource)
{
    if (pcSource == NULL)
    {
        return pcSource;
    }

    char *pcTemp = pcSource;
    
    while (*pcTemp == ' ' || *pcTemp == '\t' 
            || *pcTemp == '\r' || *pcTemp == '\n')
    {
        pcTemp++;
    }

    if (pcTemp != pcSource)
    {
        char *pcNew = pcSource;
        do
        {
            *pcNew++ = *pcTemp;  
        }while(*pcTemp++);
    }

    return pcSource;

}

/******************************************************************************
  函数名：rtrim
  功能描述：
    去除字符串尾部的空白（空格、tab、回车、换行）

  输入参数：
    char * 待处理字符串

  输出参数：
    char * 处理后的字符串

  返回值：
    char * 处理后的字符串
 *****************************************************************************/
char *rtrim(char *pcSource)
{
    if (pcSource == NULL)
    {
        return pcSource;
    }

    char *pcTemp = pcSource;

    while(*pcSource)
    {
        pcSource++;
    }

    while (*--pcSource == ' ' || *pcSource == '\t' 
            || *pcSource == '\r' || *pcSource == '\n')
    {
        *pcSource = '\0'; /* 注意：如果pcSource是只读的缓冲区，此处会导致SegFault!*/
    } 

    return pcTemp;
}

/******************************************************************************
  函数名：trim
  功能描述：
    去除字符串两端的空白（空格、tab、回车、换行）

  输入参数：
    char * 待处理字符串

  输出参数：
    char * 处理后的字符串

  返回值：
    char * 处理后的字符串
 *****************************************************************************/
char *trim(char *pcSource)
{
    ltrim(pcSource);
    rtrim(pcSource);

    return pcSource;
}

/******************************************************************************
  函数名：trimComment
  功能描述：
    删除自commentSign字符开始的所有注释内容 

  输入参数：
    char * 待处理字符串
    char   注释符

  输出参数：
    char * 处理后字符串

  返回值：
    无
 *****************************************************************************/
void trimComment(char *pcSource, char commentSign)
{
    char *comment;
    if ((comment = strchr(pcSource, commentSign)) != (char *)0)
    {
        int iCommentLen = strlen(comment);
        int iNonCommentLen = strlen(pcSource) - iCommentLen;
        if (iNonCommentLen == 0)
        {
            bzero(pcSource, strlen(pcSource));
        }
        else
        {
            char *pcNew = substr(pcSource, 0, iNonCommentLen);
            bzero(pcSource, strlen(pcSource));
            strncpy(pcSource, pcNew, iNonCommentLen);
        }
    } 
}

/******************************************************************************
  函数名：replaceChar
  功能描述：
    将字符串中所有出现的某个单个字符替换为新的指定字符 
 
  输入参数：
    char * 待处理字符串
    char   目标被替换字符
    char   新字符

  输出参数：
    无

  返回值：
    char * 处理后的字符串
 *****************************************************************************/
char *replaceChar(char *pcSource, char cOld, char cNew)
{
    if(pcSource == NULL)
    {
        return pcSource;
    }
    char *pcTemp = pcSource;

    while (pcSource && *pcSource)
    {
        if (*pcSource == cOld)
        {
            *pcSource = cNew;
        }
        pcSource++;
    }

    return pcTemp;
}

/******************************************************************************
  函数名：countWords
  功能描述：
    计算字符串中指定字串出现的次数  

  输入参数：
    char *       目标字符串
    const char * 查找子串

  输出参数：
    无
    
  返回值：
    int     子串在目标字符串中出现的次数
 *****************************************************************************/
int countWords(char *pcSource, const char *pcWord)
{
    if (pcSource == NULL || pcWord == NULL)
    {
        return 0;
    }


    int i = 0;
    char *pcTemp = pcSource;

    while ((pcTemp = strstr(pcTemp, pcWord)))
    {
        i++;
        pcTemp++;
    }

    return i;

}

/******************************************************************************
  函数名：replaceString
  功能描述：
    将字符串中的所有出现的某个子串替换为新的子串  

  输入参数：
    char *         待处理字符串
    const char *   目标被替换子串
    const char *   新子串

  输出参数：
    无

  返回值：
    char * 处理后的字符串
 *****************************************************************************/
char *replaceString(char **pcSource, const char *pcOld, const char *pcNew)
{
    int i;
    int d;

    if (pcSource == NULL || *pcSource == NULL)
    {
        return *pcSource;
    }

    if (pcOld == NULL || pcNew == NULL)
    {
        return *pcSource;
    }

    i = countWords(*pcSource, pcOld);
    d = strlen(pcNew) - strlen(pcOld);  

    if (i == 0)
    {
        return *pcSource;
    }

    if (d > 0) /* 新子串长度超过被替换子串的长度 */
    {
        d *= i; /* 需要新申请的字节数 */
    }
    else
    {
        d = 0;
    }

    char *p;
    char *q;

    int l = strlen(pcOld);
    char *buf = (char *)calloc(strlen(*pcSource) + d + 1, sizeof(char));

    q = *pcSource;
    *buf = '\0';

    while ((p = strstr(q, pcOld)))
    {
        *p = '\0';
        strcat(buf, q);
        strcat(buf, pcNew);
        p += l;
        q = p;
    }

    strcat(buf, q);
    if(*pcSource)
        free(*pcSource);
    *pcSource = buf;

    return *pcSource;
}

/******************************************************************************
  函数名：handleEscape
  功能描述：
    处理\转义字符

  输入参数：
    char * 待处理字符串

  输出参数：
    char * 处理后的字符串

  返回值：
    int    处理后的字符串的长度
 *****************************************************************************/
int handleEscape(char *pcSource)
{
    if (pcSource == NULL)
    {
        return 0;
    }
    
    int iEditPos = 0;
    int iInsertPos = 0;

    for (; *(pcSource + iEditPos) != '\0'; iEditPos++, iInsertPos++)
    {
        if (*(pcSource + iEditPos) == '\\')
        {
            switch(*(pcSource + iEditPos + 1))
            {
                case 'n':
                    *(pcSource + iInsertPos) = '\n';
                    iEditPos++;
                    break;

                case 't':
                    *(pcSource + iInsertPos) = '\t';
                    iEditPos++;
                    break;
                
                case 'r':
                    *(pcSource + iInsertPos) = '\r';
                    iEditPos++;
                    break;

                case ' ':
                    *(pcSource + iInsertPos) = ' ';
                    iEditPos++;
                    break;

                case '0':
                    if (*(pcSource + iEditPos + 2) == 'x') /* \0x */
                    {
                        if (*(pcSource + iEditPos + 3) == '0' &&
                                *(pcSource + iEditPos + 4) == '0') /* \0x00 */
                        {
                            *(pcSource + iInsertPos) = *(pcSource + iEditPos);
                        }
                        else
                        {
                            *(pcSource + iInsertPos) = hex2char(&pcSource[iEditPos + 3]);
                            iEditPos += 4;
                        }
                    }
                    break;

                case '\\':
                    *(pcSource + iInsertPos) = '\\';
                    iEditPos++;
                    break;

                default:
                    *(pcSource + iInsertPos) = *(pcSource + iEditPos);

            }
        }
        else
        {
            *(pcSource + iInsertPos) = *(pcSource + iEditPos);

        }
    }
   
   *(pcSource + iInsertPos) = '\0'; 

   return iInsertPos;
}

/******************************************************************************
  函数名：handle0Escape
  功能描述：
    处理\0x00转义字符

  输入参数：
    char * 待处理字符串

  输出参数：
    char * 处理后的字符串

  返回值：
    int   处理后的字符串的长度
 *****************************************************************************/
int handle0Escape(char *pcSource)
{
    if (pcSource == NULL)
    {
        return 0;
    }

    int iEditPos = 0;
    int iInsertPos = 0;

    for (; *(pcSource + iEditPos) != '\0'; iEditPos++, iInsertPos++)
    {
        if (*(pcSource + iEditPos) == '\\')
        {
            switch(*(pcSource + iEditPos + 1))
            {
                case '0':
                    if (*(pcSource + iEditPos + 2) == 'x') /* \0x */
                    {
                        *(pcSource + iInsertPos) = hex2char(&pcSource[iEditPos + 3]);
                        iEditPos += 4;
                    }
                    break;

                default:
                    *(pcSource + iInsertPos) = *(pcSource + iEditPos);

            }
        }
        else
        {
            *(pcSource + iInsertPos) = *(pcSource + iEditPos);

        }
    }

    *(pcSource + iInsertPos) = '\0';

    return iInsertPos; 

}

/******************************************************************************
  函数名：hex2char
  功能描述：
    16进制字符串转为ASCII码字符值

  输入参数：
    char * 待处理字符串

  输出参数：
    无

  返回值：
    char    转换后的ASCII码字符值
 *****************************************************************************/
char hex2char(char *pcHex)
{
    register char digit;
    digit = ((pcHex[0] >= 'A') ? ((pcHex[0] & 0xdf) - 'A') + 10 : (pcHex[0] - '0'));
    digit *= 16;
    digit += ((pcHex[1] >= 'A') ? ((pcHex[1] & 0xdf) - 'A') + 10 : (pcHex[1] - '0'));

    return digit;
}

/******************************************************************************
  函数名：substr
  功能描述：
    截取指定长度的字符串

  输入参数：
    char * 待截取的字符串
    size_t 子串的起始截取位置（相对于待截取字符串的起始偏移位置）
    size_t 截取子串的长度


  输出参数：
    无

  返回值：
    char * 截取出的子字符串（注意：该函数返回的字符串是通过调用strndup获得的，
                                   因此需要手工释放str所指向的内存 ）
 *****************************************************************************/
char *substr(const char* str, size_t begin, size_t len)
{
    if (str == NULL || strlen(str) == 0 || strlen(str) < begin || strlen(str) < (begin + len) || len <= 0)
    {
        return (char *)0;
    }

    return strndup(str + begin, len);
}

/******************************************************************************
  函数名：substra
  功能描述：
    截取指定长度的字符串

  输入参数：
    char * 待截取的字符串
    size_t 子串的起始截取位置（相对于待截取字符串的起始偏移位置）
    size_t 截取子串的长度


  输出参数：
    无

  返回值：
    char * 截取出的子字符串
 *****************************************************************************/
char *substra(const char* str, size_t begin, size_t len)
{
    if (str == NULL || strlen(str) == 0 || strlen(str) < begin || strlen(str) < (begin + len))
    {
        return 0;
    }

    return strndupa(str + begin, len);
}


